服务提供者框架中有四个重要的组件:
- 服务接口(Service Interface):由服务提供者实现,用来抽象服务提供者提供的服务。
- 提供者注册API(Provider Registration API):系统用来注册实现,让客户端访问它们的。
- 服务访问API(Service Access API):客户端用来获取服务的实例。
- 服务提供者接口(Service Provider Interface):可选,由服务提供者实现,用来抽象服务提供者。
JDBC的实现就是一个服务者提供框架应用的典型例子。
JDK版本:oracle java 1.8.0_102
JDBC与服务者提供框架
JDBC中的各角色
JDBC的实现中包含有服务提供者接口,具体如下:
- 服务接口:Connection
- 服务提供者接口:Driver
- 提供者注册API:DriverManager.registerDriver()方法
- 服务访问API:DriverManager.getConnection()方法
具体实现
服务接口:Connection
Connection即为数据库连接服务,没什么特殊的,注意接口的多继承:
1 2 3
| public interface Connection extends Wrapper, AutoCloseable { … }
|
服务提供者接口:Driver
Driver生成Connection服务:
1 2 3 4 5 6
| public interface Driver { … Connection connect(String url, java.util.Properties info) throws SQLException; … }
|
记住Driver#connect()方法,后面还会见到。
提供者注册API:DriverManager.registerDriver()方法
服务的提供者实现Driver类,通过DriverManager.registerDriver()将服务提供者的实例注册到DriverManager中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class DriverManager { … public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { registerDriver(driver, null); } … public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException { if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); } else { throw new NullPointerException(); } println("registerDriver: " + driver); } … }
|
具体的注册行为由服务提供者发起。MySQL的Driver实现com.mysql.jdbc.Driver为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Driver extends NonRegisteringDriver implements java.sql.Driver { … static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } … public Driver() throws SQLException { } … }
|
可知,在第一次加载com.mysql.jdbc.Driver时,com.mysql.jdbc.Driver会利用静态代码块调用提供者注册API DriverManager.registerDriver()。
服务访问API:DriverManager.getConnection()方法
注册服务提供者的实例后,服务提供者就能够通过框架提供服务。具体来说,可通过静态工厂方法DriverManager.getConnection()提供Connection服务,底层是通过Driver接口的实现类实现的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class DriverManager { … public static Connection getConnection(String url) throws SQLException { java.util.Properties info = new java.util.Properties(); return (getConnection(url, info, Reflection.getCallerClass())); } … private static Connection getConnection( … for(DriverInfo aDriver : registeredDrivers) { if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); Connection con = aDriver.driver.connect(url, info); if (con != null) { println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } … } … }
|
注意这里的命名方式getConnection,目前的实现中,每次返回的是新的Connection实例,感觉叫做newConnection更恰当。不知道为什么这样命名。
这里的逻辑很简单,遍历所有已注册的Driver实现类,选择第一个可用的Driver创建Connection。还记得Driver#connect()方法吗?aDriver.driver.connect
一句中,由底层Driver完成Connection的创建。
done